#ifndef __UDPSERVER_HPP__
#define __UDPSERVER_HPP__

#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include <cerrno>
#include <strings.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Log.hpp"
using namespace LogModule;

const int global_sockfd = -1;
const int global_port = 8888;

class UdpServer
{
public:
    UdpServer(uint16_t port = global_port)
        : _port(port), _sockfd(global_sockfd), _is_running(false)
    {
    }

    ~UdpServer()
    {
        if (_sockfd > global_sockfd)
        {
            close(_sockfd);
        }
    }

    void Init()
    {
        // 创建套接字socket
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); //(协议族，类型，协议) 返回文件描述符
        if (_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error:" << strerror(errno);
            exit(1);
        }
        LOG(LogLevel::INFO) << "socket succeed , socket fd is:" << _sockfd;

        // 绑定地址
        struct sockaddr_in addr;
        memset(&addr, 0, sizeof(addr));           // 清空结构体
        addr.sin_family = AF_INET;                // 协议族
        addr.sin_port = htons(_port);             // 端口号
        addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip地址,INADDR_ANY表示任意地址,即0.0.0.0

        int n = bind(_sockfd, (struct sockaddr *)&addr, sizeof(addr));
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error:" << strerror(errno);
            exit(2);
        }
        LOG(LogLevel::INFO) << "bind succeed , port is:" << _port;
    }

    void Start()
    {
        _is_running=true;
        while(1)
        {
            if(!_is_running)
            {
                break;
            }

            // 接收数据
            char buf[1024] = {0};
            struct sockaddr_in peer_addr;
            socklen_t peer_addr_len = sizeof(peer_addr);
            ssize_t n = recvfrom(_sockfd, buf, sizeof(buf)-1, 0, (struct sockaddr *)&peer_addr, &peer_addr_len);
            if (n < 0)
            {
                LOG(LogLevel::ERROR) << "recvfrom error:" << strerror(errno);
                continue;
            }
            else if(n > 0)
            {
                //获取client的ip和port
                std::string client_ip = inet_ntoa(peer_addr.sin_addr);
                uint16_t client_port = ntohs(peer_addr.sin_port);
                LOG(LogLevel::INFO) << "client ip:" << client_ip << " port:" << client_port << " msg:" << buf;

                // 发送数据 示例：信息***已收到
                std::string msg = "信息:"+std::string(buf)+" 已收到";
                n = sendto(_sockfd, msg.c_str(), msg.size(), 0, (struct sockaddr *)&peer_addr, peer_addr_len);
                if (n < 0)
                {
                    LOG(LogLevel::ERROR) << "sendto error:" << strerror(errno);
                }
            }
        }


        _is_running=false;
    }

private:
    int _sockfd; // socket fd
    // std::string _ip;// ip
    uint16_t _port;
    bool _is_running;
};

#endif // __UDPSERVER_HPP__